home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / JFC.bin / JSlider.java < prev    next >
Text File  |  1998-06-30  |  28KB  |  917 lines

  1. /*
  2.  * @(#)JSlider.java    1.59 98/02/16
  3.  * 
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  */
  20.  
  21. package com.sun.java.swing;
  22.  
  23. import com.sun.java.swing.border.*;
  24. import com.sun.java.swing.event.*;
  25. import com.sun.java.swing.plaf.*;
  26. import com.sun.java.accessibility.*;
  27.  
  28. import java.io.Serializable;
  29. import java.util.*;
  30.  
  31.  
  32. /**
  33.  * A component that lets the user graphically select a value by slding
  34.  * a knob within a bounded interval. The slider can show both 
  35.  * major tick marks and minor tick marks between them. The number of
  36.  * pixels between the tick marks is controlled with 
  37.  * <code>setMajorTickSpacing</code> and <code>setMinorTickSpacing</code>. 
  38.  * <p>
  39.  * For the keyboard keys used by this component in the standard Look and
  40.  * Feel (L&F) renditions, see the
  41.  * <a href="doc-files/Key-Index.html#JSlider">JSlider</a> key assignments.
  42.  * <p>
  43.  * Warning: serialized objects of this class will not be compatible with
  44.  * future swing releases.  The current serialization support is appropriate
  45.  * for short term storage or RMI between Swing1.0 applications.  It will
  46.  * not be possible to load serialized Swing1.0 objects with future releases
  47.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  48.  * baseline for the serialized form of Swing objects.
  49.  *
  50.  * @beaninfo
  51.  *      attribute: isContainer false
  52.  *    description: A component that supports selecting a integer value from a range.
  53.  * 
  54.  * @version 1.59 02/16/98
  55.  * @author David Kloba
  56.  */
  57. public class JSlider extends JComponent implements SwingConstants, Accessible
  58. {
  59.     /**
  60.      * The data model that handles the numeric maximum value,
  61.      * minimum value, and current-position value for the slider.
  62.      */
  63.     protected BoundedRangeModel sliderModel;
  64.  
  65.     /**
  66.      * The number of pixels between the major tick marks -- the 
  67.      * larger marks that break up the minor tick marks.
  68.      */
  69.     protected int majorTickSpacing;
  70.  
  71.     /**
  72.      * The number of pixels between the minor tick marks -- the 
  73.      * smaller marks that occur between the major tick marks.
  74.      * @see #setMinorTickSpacing
  75.      */
  76.     protected int minorTickSpacing;
  77.  
  78.     /**
  79.      * If true, the knob (and the data value it represents) 
  80.      * resolve to the closest tick mark next to where the user
  81.      * positioned the knob.
  82.      * @see #setSnapToTicks
  83.      */
  84.     protected boolean snapToTicks = true;
  85.  
  86.     private boolean paintTicks = false;
  87.     private boolean paintLabels = false;
  88.     private boolean isInverted = false;
  89.  
  90.  
  91.     /**
  92.      * @see #setOrientation
  93.      */
  94.     protected int orientation;
  95.  
  96.  
  97.     /**
  98.      * Whether the component fully paints all of the pixels in its
  99.      * region. By default this component is not transparent, so the 
  100.      * value is true. Use <code>setOpaque</code> to make the sliders
  101.      * background transparent, so that pixels under the slider 
  102.      * "show through" in the area the knob moves in.
  103.      */
  104.     private Dictionary labelTable;
  105.     
  106.  
  107.     /**
  108.      * The changeListener (no suffix) is the listener we add to the
  109.      * Sliders model.  By default this listener just forwards events
  110.      * to ChangeListeners (if any) added directly to the slider.
  111.      * 
  112.      * @see #addChangeListener
  113.      * @see #createChangeListener
  114.      */
  115.     protected ChangeListener changeListener = createChangeListener();
  116.  
  117.    
  118.     /**
  119.      * Only one ChangeEvent is needed per slider instance since the
  120.      * event's only (read-only) state is the source property.  The source
  121.      * of events generated here is always "this". The event is lazily
  122.      * created the first time that an event notification is fired.
  123.      * 
  124.      * @see #fireStateChanged
  125.      */
  126.     protected transient ChangeEvent changeEvent = null;
  127.  
  128.  
  129.     private void checkOrientation(int orientation) {
  130.         switch (orientation) {
  131.         case VERTICAL:
  132.         case HORIZONTAL:
  133.             break;
  134.         default:
  135.             throw new IllegalArgumentException("orientation must be one of: VERTICAL, HORIZONTAL");
  136.         }
  137.     }
  138.  
  139.  
  140.     /**
  141.      * Creates a slider with the specified orientation and the
  142.      * specified mimimum, maximum, and initial values.
  143.      * 
  144.      * @exception IllegalArgumentException if orientation is not one of VERTICAL, HORIZONTAL
  145.      *
  146.      * @see #setOrientation
  147.      * @see #setMinimum
  148.      * @see #setMaximum
  149.      * @see #setValue
  150.      */
  151.     public JSlider(int orientation, int min, int max, int value) 
  152.     {
  153.         checkOrientation(orientation);
  154.         this.orientation = orientation;
  155.         sliderModel = new DefaultBoundedRangeModel(value, 0, min, max);
  156.         sliderModel.addChangeListener(changeListener);
  157.         updateUI();
  158.     }
  159.  
  160.  
  161.     /**
  162.      * Creates a horizontal slider with the range 0 to 100 and
  163.      * an intitial value of 50.
  164.      */
  165.     public JSlider() {
  166.         this(HORIZONTAL, 0, 100, 50);
  167.     }
  168.  
  169.  
  170.     /**
  171.      * Gets the UI object which implements the L&F for this component.
  172.      *
  173.      * @return the SliderUI object that implements the Slider L&F
  174.      */
  175.     public SliderUI getUI() {
  176.         return (SliderUI)ui;
  177.     }
  178.  
  179.  
  180.     /**
  181.      * Sets the UI object which implements the L&F for this component.
  182.      *
  183.      * @param ui the SliderUI L&F object
  184.      * @see UIDefaults#getUI
  185.      * @beaninfo
  186.      *       bound: true
  187.      *      hidden: true
  188.      * description: The UI object that implements the slider's LookAndFeel. 
  189.      */
  190.     public void setUI(SliderUI ui) {
  191.         super.setUI(ui);
  192.     }
  193.  
  194.  
  195.     /**
  196.      * Notification from the UIFactory that the L&F has changed. 
  197.      * Called to replace the UI with the latest version from the 
  198.      * default UIFactory.
  199.      *
  200.      * @see JComponent#updateUI
  201.      */
  202.     public void updateUI() {
  203.         updateLabelUIs();
  204.         setUI((SliderUI)UIManager.getUI(this));
  205.     }
  206.  
  207.  
  208.     /**
  209.      * Returns the name of the L&F class that renders this component.
  210.      *
  211.      * @return "SliderUI"
  212.      * @see JComponent#getUIClassID
  213.      * @see UIDefaults#getUI
  214.      */
  215.     public String getUIClassID() {
  216.         return "SliderUI";
  217.     }
  218.  
  219.  
  220.     /**
  221.      * We pass Change events along to the listeners with the 
  222.      * the slider (instead of the model itself) as the event source.
  223.      */
  224.     private class ModelListener implements ChangeListener, Serializable {
  225.         public void stateChanged(ChangeEvent e) {
  226.             fireStateChanged();
  227.         }
  228.     }
  229.  
  230.  
  231.     /**
  232.      * Subclasses that want to handle model ChangeEvents differently
  233.      * can override this method to return their own ChangeListener 
  234.      * implementation.  The default ChangeListener just forwards 
  235.      * ChangeEvents to the ChangeListeners added directly to the slider.
  236.      * 
  237.      * @see #fireStateChanged
  238.      */
  239.     protected ChangeListener createChangeListener() {
  240.         return new ModelListener();
  241.     }
  242.  
  243.  
  244.     /**
  245.      * Adds a ChangeListener to the slider.
  246.      *
  247.      * @param l the ChangeListener to add
  248.      * @see #fireStateChanged
  249.      * @see #removeChangeListener
  250.      */
  251.     public void addChangeListener(ChangeListener l) {
  252.         listenerList.add(ChangeListener.class, l);
  253.     }
  254.     
  255.  
  256.     /**
  257.      * Removes a ChangeListener from the slider.
  258.      *
  259.      * @param l the ChangeListener to remove
  260.      * @see #fireStateChanged
  261.      * @see #addChangeListener
  262.  
  263.      */
  264.     public void removeChangeListener(ChangeListener l) {
  265.         listenerList.remove(ChangeListener.class, l);
  266.     }
  267.         
  268.  
  269.     /**
  270.      * Send a ChangeEvent, whose source is this Slider, to
  271.      * each listener.  This method method is called each time 
  272.      * a ChangeEvent is received from the model.
  273.      * 
  274.      * @see #addChangeListener
  275.      * @see EventListenerList
  276.      */
  277.     protected void fireStateChanged() {
  278.         Object[] listeners = listenerList.getListenerList();
  279.         for (int i = listeners.length - 2; i >= 0; i -= 2) {
  280.             if (listeners[i]==ChangeListener.class) {
  281.                 if (changeEvent == null) {
  282.                     changeEvent = new ChangeEvent(this);
  283.                 }
  284.                 ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
  285.             }          
  286.         }
  287.     }   
  288.  
  289.  
  290.     /**
  291.      * Returns data model that handles the sliders three 
  292.      * fundamental properties: minimum, maximum, value.
  293.      * 
  294.      * @see #setModel
  295.      */
  296.     public BoundedRangeModel getModel() {
  297.         return sliderModel;
  298.     }
  299.  
  300.  
  301.     /**
  302.      * Sets the model that handles the sliders three 
  303.      * fundamental properties: minimum, maximum, value.
  304.      * 
  305.      * @see #getModel
  306.      * @beaninfo
  307.      *       bound: true
  308.      * description: The sliders BoundedRangeModel.
  309.      */
  310.     public void setModel(BoundedRangeModel newModel) 
  311.     {
  312.         BoundedRangeModel oldModel = getModel();
  313.  
  314.         if (oldModel != null) {
  315.             oldModel.removeChangeListener(changeListener);
  316.         }
  317.  
  318.         sliderModel = newModel;
  319.  
  320.         if (newModel != null) {
  321.             newModel.addChangeListener(changeListener);
  322.  
  323.             if (accessibleContext != null) {
  324.                 accessibleContext.firePropertyChange(
  325.                         AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
  326.                         (oldModel == null 
  327.                          ? null : new Integer(oldModel.getValue())),
  328.                         (newModel == null 
  329.                          ? null : new Integer(newModel.getValue())));
  330.             }
  331.         }
  332.  
  333.         firePropertyChange("model", oldModel, sliderModel);
  334.     }
  335.  
  336.  
  337.     /**
  338.      * Returns the sliders value.
  339.      * @return the models value property
  340.      * @see #setValue
  341.      */
  342.     public int getValue() { 
  343.         return getModel().getValue(); 
  344.     }
  345.  
  346.  
  347.     /**
  348.      * Sets the sliders current value.  This method just forwards
  349.      * the value to the model.
  350.      * 
  351.      * @see #getValue
  352.      * @beaninfo
  353.      *   preferred: true
  354.      * description: The sliders current value.
  355.      */
  356.     public void setValue(int n) { 
  357.         BoundedRangeModel m = getModel();
  358.         int oldValue = m.getValue();
  359.         m.setValue(n);
  360.  
  361.         if (accessibleContext != null) {
  362.             accessibleContext.firePropertyChange(
  363.                     AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
  364.                     new Integer(oldValue),
  365.                     new Integer(m.getValue()));
  366.         }
  367.     }
  368.  
  369.  
  370.     /**
  371.      * Returns the minimum value supported by the slider. 
  372.      *
  373.      * @return the value of the models minimum property
  374.      * @see #setMinimum
  375.      */
  376.     public int getMinimum() { 
  377.         return getModel().getMinimum(); 
  378.     }
  379.  
  380.  
  381.     /**
  382.      * Sets the models minimum property.
  383.      *
  384.      * @see #getMinimum
  385.      * @see BoundedRangeModel#setMinimum
  386.      * @beaninfo
  387.      *   preferred: true
  388.      * description: The sliders minimum value.
  389.      */
  390.     public void setMinimum(int minimum) { 
  391.         getModel().setMinimum(minimum); 
  392.     }
  393.  
  394.  
  395.     /**
  396.      * Returns the maximum value supported by the slider.
  397.      *
  398.      * @return the value of the models maximum property
  399.      * @see #setMaximum
  400.      */
  401.     public int getMaximum() { 
  402.         return getModel().getMaximum(); 
  403.     }
  404.  
  405.  
  406.     /**
  407.      * Sets the models maximum property.  
  408.      * 
  409.      * @see #getMaximum
  410.      * @see BoundedRangeModel#setMaximum
  411.      * @beaninfo
  412.      *   preferred: true
  413.      * description: The sliders maximum value.
  414.      */
  415.     public void setMaximum(int maximum) { 
  416.         getModel().setMaximum(maximum); 
  417.     }
  418.  
  419.  
  420.     /**
  421.      * True if the slider knob is being dragged.
  422.      * 
  423.      * @return the value of the models valueIsAdjusting property
  424.      * @see #setValueIsAdjusting
  425.      */
  426.     public boolean getValueIsAdjusting() { 
  427.         return getModel().getValueIsAdjusting(); 
  428.     }
  429.  
  430.  
  431.     /**
  432.      * Sets the models valueIsAdjusting property.  Slider look and
  433.      * feel implementations should set this property to true when 
  434.      * a knob drag begins, and to false when the drag ends.  The
  435.      * slider model will not generate ChangeEvents while
  436.      * valueIsAdjusting is true.
  437.      * 
  438.      * @see #getValueIsAdjusting
  439.      * @see BoundedRangeModel#setValueIsAdjusting
  440.      * @beaninfo
  441.      *      expert: true
  442.      * description: True if the slider knob is being dragged.
  443.      */
  444.     public void setValueIsAdjusting(boolean b) { 
  445.         BoundedRangeModel m = getModel();   
  446.         boolean oldValue = m.getValueIsAdjusting();
  447.         m.setValueIsAdjusting(b);
  448.    
  449.         if ((oldValue != b) && (accessibleContext != null)) {
  450.             accessibleContext.firePropertyChange(
  451.                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  452.                     ((oldValue) ? AccessibleState.BUSY : null),
  453.                     ((b) ? AccessibleState.BUSY : null));
  454.         }
  455.     }
  456.  
  457.  
  458.     /**
  459.      * @return the range of values "covered" by the knob.
  460.      * @see #setExtent
  461.      * @see BoundedRangeModel#getExtent
  462.      */
  463.     public int getExtent() { 
  464.         return getModel().getExtent(); 
  465.     }
  466.  
  467.  
  468.     /**
  469.      * Sets the size of the range "covered" by the knob.  Most look
  470.      * and feel implementations will change the value by this amount
  471.      * if the user clicks on either side of the knob.
  472.      * 
  473.      * @see #getExtent
  474.      * @see BoundedRangeModel#setExtent
  475.      * @beaninfo
  476.      *      expert: true
  477.      * description: Size of the range covered by the knob.
  478.      */
  479.     public void setExtent(int extent) { 
  480.         getModel().setExtent(extent); 
  481.     }
  482.  
  483.  
  484.     /**
  485.      * @return VERTICAL or HORIZONTAL
  486.      * @see #setOrientation
  487.      */
  488.     public int getOrientation() { 
  489.         return orientation; 
  490.     }
  491.  
  492.  
  493.     /**
  494.      * Set the scrollbars orientation to either VERTICAL or HORIZONTAL.
  495.      * 
  496.      * @exception IllegalArgumentException if orientation is not one of VERTICAL, HORIZONTAL
  497.      * @see #getOrientation
  498.      * @beaninfo
  499.      *   preferred: true
  500.      *       bound: true
  501.      * description: Set the scrollbars orientation to either VERTICAL or HORIZONTAL.
  502.      *        enum: VERTICAL JSlider.VERTICAL 
  503.      *              HORIZONTAL JSlider.HORIZONTAL
  504.      * 
  505.      */
  506.     public void setOrientation(int orientation) 
  507.     { 
  508.         checkOrientation(orientation);
  509.         int oldValue = orientation;
  510.         this.orientation = orientation;
  511.         firePropertyChange("orientation", oldValue, orientation);
  512.  
  513.         if ((oldValue != orientation) && (accessibleContext != null)) {
  514.             accessibleContext.firePropertyChange(
  515.                     AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  516.                     ((oldValue == VERTICAL) 
  517.                      ? AccessibleState.VERTICAL : AccessibleState.HORIZONTAL),
  518.                     ((orientation == VERTICAL) 
  519.                      ? AccessibleState.VERTICAL : AccessibleState.HORIZONTAL));
  520.         }
  521.     }
  522.  
  523.  
  524.  
  525.     /**
  526.      * Returns the dictionary of what labels to draw at which values.
  527.      *
  528.      * @return the Dictionary containing labels and where to draw them
  529.      */
  530.     public Dictionary getLabelTable() {
  531. /*
  532.         if ( labelTable == null && getMajorTickSpacing() > 0 ) {
  533.             setLabelTable( createStandardLabels( getMajorTickSpacing() ) );
  534.         }
  535. */
  536.         return labelTable;
  537.     }
  538.  
  539.  
  540.     /**
  541.      * Used to specify what label will be drawn at any given value.
  542.      * The key-value pairs are of this format: <B>{ Integer value, java.awt.Component label }</B>
  543.      *
  544.      * @see #createStandardLabels
  545.      * @see #getLabelTable
  546.      * @beaninfo
  547.      *      hidden: true
  548.      *       bound: true
  549.      * description: Specifies what labels will be drawn for any given value.
  550.      */
  551.     public void setLabelTable( Dictionary labels ) {
  552.         Dictionary oldTable = labelTable;
  553.         labelTable = labels;
  554.         updateLabelUIs();
  555.         firePropertyChange("labelTable", oldTable, labelTable );
  556.     }
  557.  
  558.  
  559.     /**
  560.      * Called internally to replace the label UIs with the latest versions
  561.      * from the UIFactory when the UIFactory notifies us via
  562.      * <code>updateUI</code> that the L&F has changed.
  563.      *
  564.      * @see JComponent#updateUI
  565.      */
  566.     protected void updateLabelUIs() {
  567.         if ( getLabelTable() == null ) {
  568.             return;
  569.         }
  570.         Enumeration labels = getLabelTable().keys();
  571.         while ( labels.hasMoreElements() ) {
  572.             Object value = getLabelTable().get( labels.nextElement() );
  573.             if ( value instanceof JComponent ) {
  574.                 JComponent component = (JComponent)value;
  575.                 component.updateUI();
  576.                 component.setSize( component.getPreferredSize()  );
  577.             }
  578.         }
  579.     }
  580.  
  581.  
  582.     /**
  583.      * Creates a hashtable that will draw text labels starting at the slider minimum using the
  584.      * increment specified. If you call createStandardLabels( 10 ) and the slider minimum is
  585.      * zero, then it will make labels for the values 0, 10, 20, 30, and so on.
  586.      * @see #setLabelTable
  587.      */
  588.     public Hashtable createStandardLabels( int increment ) {
  589.         return createStandardLabels( increment, getMinimum() );
  590.     }
  591.  
  592.  
  593.     /**
  594.      * Creates a hashtable that will draw text labels starting at the start point
  595.      * specified using the increment specified. If you call createStandardLabels( 10, 2 ),
  596.      * then it will make labels for the values 2, 12, 22, 32, and so on.
  597.      * @see #setLabelTable
  598.      */
  599.     public Hashtable createStandardLabels( int increment, int start ) {
  600.         if ( start > getMaximum() || start < getMinimum() ) {
  601.             throw new IllegalArgumentException( "Slider label start point out of range." );
  602.         }
  603.  
  604.         Hashtable table = new Hashtable();
  605.  
  606.         for ( int labelIndex = start; labelIndex <= getMaximum(); labelIndex += increment ) {
  607.             table.put( new Integer( labelIndex ), new JLabel( ""+labelIndex, JLabel.CENTER ) );
  608.         }
  609.  
  610.         return table;
  611.     }
  612.  
  613.  
  614.     /**
  615.      * Returns true if the value-range shown for the slider is reversed,
  616.      * with the maximum value at the left end of a horizontal slider or
  617.      * at the bottom of a vertical one.
  618.      *
  619.      * @return true if the slider values are reversed from their normal order
  620.      */
  621.     public boolean getInverted() { 
  622.         return isInverted; 
  623.     }
  624.     
  625.  
  626.     /**
  627.      * Specify true to reverse the value-range shown for the slider so that
  628.      * the maximum value is at the left end of a horizontal slider or
  629.      * at the bottom of a vertical one. Specify false to put the value range
  630.      * in the normal order.
  631.      *
  632.      * @param b  true to reverse the slider values from their normal order
  633.      * @beaninfo
  634.      *       bound: true
  635.      * description: If true reverses the slider values from their normal order 
  636.      * 
  637.      */
  638.     public void setInverted( boolean b ) { 
  639.         boolean oldValue = isInverted;
  640.         isInverted = b; 
  641.         firePropertyChange("inverted", oldValue, isInverted);
  642.     }
  643.  
  644.  
  645.     /**
  646.      * @return the number of pixels between major ticks
  647.      * @see #setMajorTickSpacing
  648.      */
  649.     public int getMajorTickSpacing() { 
  650.         return majorTickSpacing; 
  651.     }
  652.  
  653.  
  654.     /**
  655.      * Sets the number of pixels between major tick marks.
  656.      * @see #getMajorTickSpacing
  657.      * @beaninfo
  658.      *       bound: true
  659.      * description: Sets the number of pixels between major tick marks.
  660.      * 
  661.      */
  662.     public void setMajorTickSpacing(int n) {
  663.         int oldValue = majorTickSpacing;
  664.         majorTickSpacing = n;
  665.         if ( labelTable == null && getMajorTickSpacing() > 0 && getPaintLabels() ) {
  666.             setLabelTable( createStandardLabels( getMajorTickSpacing() ) );
  667.         }
  668.         firePropertyChange("majorTickSpacing", oldValue, majorTickSpacing);
  669.     }
  670.  
  671.  
  672.     
  673.     /**
  674.      * @return the number of pixels between minor ticks
  675.      * @see #getMinorTickSpacing
  676.      */
  677.     public int getMinorTickSpacing() { 
  678.         return minorTickSpacing; 
  679.     }
  680.  
  681.  
  682.     /**
  683.      * Sets the number of pixels between minor tick marks.
  684.      * @see #getMinorTickSpacing
  685.      * @beaninfo
  686.      *       bound: true
  687.      * description: Sets the number of pixels between minor tick marks.
  688.      */
  689.     public void setMinorTickSpacing(int n) { 
  690.         int oldValue = minorTickSpacing;
  691.         minorTickSpacing = n; 
  692.         firePropertyChange("minorTickSpacing", oldValue, minorTickSpacing);
  693.     }
  694.  
  695.  
  696.     /**
  697.      * Returns true if the knob (and the data value it represents) 
  698.      * resolve to the closest tick mark next to where the user
  699.      * positioned the knob.
  700.      *
  701.      * @return true if the value snaps to the nearest tick mark, else false
  702.      * @see #setSnapToTicks
  703.      */
  704.     public boolean getSnapToTicks() { 
  705.         return snapToTicks; 
  706.     }
  707.  
  708.  
  709.     /**
  710.      * Specifying true makes the knob (and the data value it represents) 
  711.      * resolve to the closest tick mark next to where the user
  712.      * positioned the knob.
  713.      *
  714.      * @param b  true to snap the knob to the nearest tick mark
  715.      * @see #getSnapToTicks
  716.      * @beaninfo
  717.      *       bound: true
  718.      * description: If true snap the knob to the nearest tick mark.
  719.      */
  720.     public void setSnapToTicks(boolean b) { 
  721.         boolean oldValue = snapToTicks;
  722.         snapToTicks = b; 
  723.         firePropertyChange("snapToTicks", oldValue, snapToTicks);
  724.     }
  725.  
  726.  
  727.     /**
  728.      * @return true if tick marks are painted, else false
  729.      * @see #setPaintTicks
  730.      */
  731.     public boolean getPaintTicks() { 
  732.         return paintTicks; 
  733.     }
  734.  
  735.  
  736.     /**
  737.      * Determines whether tick marks are painted on the slider.
  738.      * @see #getPaintTicks
  739.      * @beaninfo
  740.      *       bound: true
  741.      * description: If true tick marks are painted on the slider.
  742.      */
  743.     public void setPaintTicks(boolean b) { 
  744.         boolean oldValue = paintTicks;
  745.         paintTicks = b;
  746.         firePropertyChange("paintTicks", oldValue, paintTicks);
  747.     }
  748.  
  749.  
  750.  
  751.     /**
  752.      * @return true if labels are painted, else false
  753.      * @see #setPaintLabels
  754.      */
  755.     public boolean getPaintLabels() { 
  756.         return paintLabels; 
  757.     }
  758.  
  759.     
  760.     /**
  761.      * Determines whether labels are painted on the slider.
  762.      * @see #getPaintLabels
  763.      * @beaninfo
  764.      *       bound: true
  765.      * description: If true labels are painted on the slider.
  766.      */
  767.     public void setPaintLabels(boolean b) {
  768.         boolean oldValue = paintLabels;
  769.         paintLabels = b;
  770.         if ( labelTable == null && getMajorTickSpacing() > 0 ) {
  771.             setLabelTable( createStandardLabels( getMajorTickSpacing() ) );
  772.         }
  773.         firePropertyChange("paintLabels", oldValue, paintLabels);
  774.     }   
  775.  
  776.  
  777.  
  778.     /**
  779.      * Returns a string containing that displays and identifies this
  780.      * object's propeties.
  781.      */
  782.     public String toString()  {
  783.         String containerString = "";
  784.  
  785.         if (!isEnabled() && !isVisible()) containerString = "(not Enabled, not Visible)";
  786.         else if (!isEnabled()) containerString = "(not Enabled)";
  787.         else if (!isVisible()) containerString = "(not Visible)";
  788.  
  789.         String sliderString =
  790.             containerString +
  791.             ((getOrientation() == 
  792.               VERTICAL) ? "vertical" : "horizontal" ) + ", " +
  793.             "value=" + getValue() + ", " +
  794.             "adj=" + getValueIsAdjusting() + ", " +
  795.             "min=" + getMinimum() + ", " +
  796.             "max=" + getMaximum() + ", " +
  797.             "majorTickSpacing=" + getMajorTickSpacing() + ", " +
  798.             "minorTickSpacing=" + getMinorTickSpacing() + ", " +
  799.             "snapToTicks=" + getSnapToTicks() + ", " +
  800.             "isInverted=" + getInverted() + ", " +
  801.             "paintLabels=" + getPaintLabels() + ", " +
  802.             "paintTicks=" + getPaintTicks();
  803.  
  804.         return getClass().getName() + "[" + sliderString + "]";
  805.     }
  806.     
  807.  
  808.  
  809. /////////////////
  810. // Accessibility support
  811. ////////////////
  812.  
  813.     /**
  814.      * Get the AccessibleContext associated with this JComponent
  815.      *
  816.      * @return the AccessibleContext of this JComponent
  817.      */
  818.     public AccessibleContext getAccessibleContext() {
  819.         if (accessibleContext == null) {
  820.             accessibleContext = new AccessibleJSlider();
  821.         }
  822.         return accessibleContext;
  823.     }
  824.  
  825.     /**
  826.      * The class used to obtain the accessible role for this object.
  827.      * <p>
  828.      * Warning: serialized objects of this class will not be compatible with
  829.      * future swing releases.  The current serialization support is appropriate
  830.      * for short term storage or RMI between Swing1.0 applications.  It will
  831.      * not be possible to load serialized Swing1.0 objects with future releases
  832.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  833.      * baseline for the serialized form of Swing objects.
  834.      */
  835.     protected class AccessibleJSlider extends AccessibleJComponent
  836.         implements AccessibleValue {
  837.  
  838.         /**
  839.          * Get the state set of this object.
  840.          *
  841.          * @return an instance of AccessibleState containing the current state 
  842.          * of the object
  843.          * @see AccessibleState
  844.          */
  845.         public AccessibleStateSet getAccessibleStateSet() {
  846.             AccessibleStateSet states = super.getAccessibleStateSet();
  847.             if (getValueIsAdjusting()) {
  848.                 states.add(AccessibleState.BUSY);
  849.             }
  850.             if (getOrientation() == VERTICAL) {
  851.                 states.add(AccessibleState.VERTICAL);
  852.             } else {
  853.                 states.add(AccessibleState.HORIZONTAL);
  854.             }
  855.             return states;
  856.         }
  857.  
  858.         /**
  859.          * Get the role of this object.
  860.          *
  861.          * @return an instance of AccessibleRole describing the role of the object
  862.          */
  863.         public AccessibleRole getAccessibleRole() {
  864.             return AccessibleRole.SLIDER;
  865.         }
  866.  
  867.         /**
  868.          * Get the AccessibleValue associated with this object if one
  869.          * exists.  Otherwise return null.
  870.          */
  871.         public AccessibleValue getAccessibleValue() {
  872.             return this;
  873.         }
  874.  
  875.         /**
  876.          * Get the accessible value of this object.
  877.          *
  878.          * @return The current value of this object.
  879.          */
  880.         public Number getCurrentAccessibleValue() {
  881.             return new Integer(getValue());
  882.         }
  883.  
  884.         /**
  885.          * Set the value of this object as a Number.
  886.          *
  887.          * @return True if the value was set.
  888.          */
  889.         public boolean setCurrentAccessibleValue(Number n) {
  890.             if (n instanceof Integer) {
  891.                 setValue(n.intValue());
  892.                 return true;
  893.             } else {
  894.                 return false;
  895.             }
  896.         }
  897.  
  898.         /**
  899.          * Get the minimum accessible value of this object.
  900.          *
  901.          * @return The minimum value of this object.
  902.          */
  903.         public Number getMinimumAccessibleValue() {
  904.             return new Integer(getMinimum());
  905.         }
  906.  
  907.         /**
  908.          * Get the maximum accessible value of this object.
  909.          *
  910.          * @return The maximum value of this object.
  911.          */
  912.         public Number getMaximumAccessibleValue() {
  913.             return new Integer(getMaximum());
  914.         }
  915.     } // AccessibleJSlider
  916. }
  917.